package com.threeti.jiayusms.framework.domain;

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;

import static com.threeti.jiayusms.framework.util.OrmUtils.unwrapOrmProxy;

/**
 * 对值对象的抽象实现<p/>
 *
 * 1.用户可自行覆写equals()和hashCode()<br/>
 *
 * 2."_surrogateKey"不具实际业务意义<br/>
 *
 * @author Jay Meng
 *
 */
public abstract class AbstractValueObject<T extends ValueObject> implements ValueObject<T> {

  private final Long _surrogateKey = null;

  private transient int _cachedHashCode = 0;
  private static final String[] EXCLUDED_FIELDS = {"_surrogateKey", "_cachedHashCode"};

  @Override
  public int hashCode() {
    int h = _cachedHashCode;
    if (h == 0) {
      h = HashCodeBuilder.reflectionHashCode(this, false);
      _cachedHashCode = h;
    }

    return h;
  }

  /**
   * @param other 另一值对象
   * @return true 如果两个值对象相等(即它们的属性相同)
   */
  @Override
  public final boolean equals(final Object other) {
    if (other == null) return false;
    if (this == other) return true;
    if (unwrapOrmProxy(this).getClass() != unwrapOrmProxy(other).getClass()) return false;

    return sameValueAs((T) other);
  }

  /**
   * 值对象通过其non-transient的属性来进行比较(非标识)，在密集调用下，可能对性能产生一定影响
   *
   * @param other 另一值对象
   * @return true 如果本值对象和目标值对象相等(它们相关的non-transient的属性相等)
   */
  protected boolean sameValueAs(T other) {
    if (other == null) return false;//double check
    return EqualsBuilder.reflectionEquals(unwrapOrmProxy(this), unwrapOrmProxy(other), EXCLUDED_FIELDS);
  }

}
